namespace HZY.Framework.Repository.EntityFramework.Attributes;

/// <summary>
/// 逻辑删除，软删除
/// </summary>
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class TableLogicAttribute : Attribute
{
    /// <summary>
    /// 非删除的值
    /// </summary>
    public object NonDeleteValue { get; set; }

    /// <summary>
    /// 删除的值
    /// </summary>
    public object DeleteValue { get; set; }

    /// <summary>
    /// 逻辑删除类型
    /// </summary>
    public TableLogicType TableLogicType { get; set; } = TableLogicType.Default;

    /// <summary>
    /// 逻辑删除，软删除
    /// </summary>
    public TableLogicAttribute()
    {
        NonDeleteValue = 0;
        DeleteValue = 1;
    }

    /// <summary>
    /// 逻辑删除，软删除
    /// </summary>
    /// <param name="nonDeleteValue"></param>
    /// <param name="deleteValue"></param>
    public TableLogicAttribute(object nonDeleteValue, object deleteValue)
    {
        NonDeleteValue = nonDeleteValue;
        DeleteValue = deleteValue;
    }

    /// <summary>
    /// 获取逻辑删除特性,的属性信息
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    public static PropertyInfo? GetTableLogicPropertyInfo(Type type)
    {
        return type.GetProperties().FirstOrDefault(x => x.GetCustomAttribute<TableLogicAttribute>() != null);
    }

    /// <summary>
    /// 根据字段填充类型获取字段
    /// </summary>
    /// <param name="propertyInfo"></param>
    /// <returns></returns>
    public static TableLogicAttribute? GetTableLogicAttribute(PropertyInfo propertyInfo)
    {
        return propertyInfo.GetCustomAttribute<TableLogicAttribute>();
    }

    /// <summary>
    /// 获取逻辑删除特性
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    public static TableLogicAttribute? GetTableLogic(Type type)
    {
        var propertyInfos = type.GetProperties();

        foreach (var propertyInfo in propertyInfos)
        {
            if (propertyInfo.GetCustomAttribute<TableLogicAttribute>() != null)
            {
                return propertyInfo.GetCustomAttribute<TableLogicAttribute>();
            }
        }

        return null;
    }

    /// <summary>
    /// 是否有逻辑删除
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    public static bool HasTableLogic(Type type)
    {
        return type.GetProperties().Any(x => x.GetCustomAttribute<TableLogicAttribute>() != null);
    }

    /// <summary>
    /// 是否是逻辑删除字段
    /// </summary>
    /// <param name="propertyInfo"></param>
    /// <returns></returns>
    public static bool IsTableLogic(PropertyInfo propertyInfo)
    {
        return propertyInfo.GetCustomAttribute<TableLogicAttribute>() != null;
    }

    /// <summary>
    /// 处理逻辑删除
    /// </summary>
    /// <param name="entityEntry"></param>
    /// <param name="propertyEntry"></param>
    /// <returns>是否标记数据已删除</returns>
    public virtual bool Handle(EntityEntry entityEntry, PropertyEntry propertyEntry)
    {
        var isSoftDeletion = false;
        var propertyType = propertyEntry.Metadata.PropertyInfo?.PropertyType;
        // 如果是 bool 类型
        if (propertyType == typeof(bool) || propertyType == typeof(bool?))
        {
            propertyEntry.CurrentValue = true;
            propertyEntry.IsModified = true;
            isSoftDeletion = true;
        }

        if (propertyType == typeof(int) || propertyType == typeof(int?))
        {
            propertyEntry.CurrentValue =
                this.TableLogicType == TableLogicType.NullOr0NonDeleteValue ? 1 : this.DeleteValue;

            propertyEntry.IsModified = true;
            isSoftDeletion = true;
        }

        if (isSoftDeletion)
        {
            entityEntry.State = EntityState.Modified;
        }

        return isSoftDeletion;
    }

    /// <summary>
    /// 获取逻辑删除的表达式
    /// </summary>
    /// <param name="entityType"></param>
    /// <param name="propertyInfo"></param>
    /// <returns></returns>
    public LambdaExpression? GetLogicExpression(Type entityType, PropertyInfo propertyInfo)
    {
        var propertyType = propertyInfo.PropertyType;
        var delName = propertyInfo.Name;
        LambdaExpression? lambdaExpression = null;

        // 如果是 bool 类型
        if (propertyType == typeof(bool) || propertyType == typeof(bool?))
        {
            if (EntityFrameworkUtil.IsNullableType(propertyType))
            {
                lambdaExpression =
                    EntityFrameworkUtil.GetFilter(entityType, $" w.{delName} == false || w.{delName} == null ");
            }
            else
            {
                lambdaExpression = EntityFrameworkUtil.GetFilter(entityType, $" !w.{delName} ");
            }
        }

        // 如果是 int 类型 ， 那么 查询 小于 0 或者 null
        if (propertyType == typeof(int) || propertyType == typeof(int?))
        {
            if (EntityFrameworkUtil.IsNullableType(propertyType))
            {
                if (TableLogicType == TableLogicType.NullOr0NonDeleteValue)
                {
                    lambdaExpression =
                        EntityFrameworkUtil.GetFilter(entityType, $" w.{delName} == 0 || w.{delName} == null ");
                }
                else if (TableLogicType == TableLogicType.LessThan1NonDeleteValue)
                {
                    lambdaExpression =
                        EntityFrameworkUtil.GetFilter(entityType, $" w.{delName} < 1");
                }
                else
                {
                    lambdaExpression = EntityFrameworkUtil.GetFilter(entityType,
                        $" w.{delName} == {NonDeleteValue} ");
                }
            }
            else
            {
                if (TableLogicType == TableLogicType.NullOr0NonDeleteValue)
                {
                    lambdaExpression = EntityFrameworkUtil.GetFilter(entityType, $" w.{delName} == 0 ");
                }
                else if (TableLogicType == TableLogicType.LessThan1NonDeleteValue)
                {
                    lambdaExpression =
                        EntityFrameworkUtil.GetFilter(entityType, $" w.{delName} < 1");
                }
                else
                {
                    lambdaExpression = EntityFrameworkUtil.GetFilter(entityType,
                        $" w.{delName} == {NonDeleteValue} ");
                }
            }
        }

        return lambdaExpression;
    }
}

public enum TableLogicType
{
    /// <summary>
    /// 默认，逻辑删除。满足 NonDeleteValue 和 DeleteValue 即可
    /// </summary>
    Default,

    /// <summary>
    /// Null 或 0 是非删除的值
    /// </summary>
    NullOr0NonDeleteValue,

    /// <summary>
    /// 小于1是非删除的值
    /// </summary>
    LessThan1NonDeleteValue,
}